#ifndef __WIZ_BNF_MATCH_HPP__SHANHAOBO_19800429__
#define __WIZ_BNF_MATCH_HPP__SHANHAOBO_19800429__

#include "../Base/WizBase.hpp"
#include "../DataType/WizDataTypeOptional.hpp"

namespace Wiz
{
    namespace BNF
    {
        namespace Match
        {
            //////////////////////////////////////////////////////
            /// RESULT
            template <typename MatchPolicyT, typename T>
            struct Result
            {
                typedef typename MatchPolicyT::template Result<T>::tType tType;
            };
            //////////////////////////////////////////////////////

            //////////////////////////////////////////////////////
            namespace Base
            {
                /// TYPE
                class Type : public ::Wiz::UnspecifiedBool::Type<Type>
                {
                    static const ::Wiz::Int::Type IllegalLength = ::Wiz::Int::Max;
                public:
                    Type() : m_Length(IllegalLength)
                    {}
                    explicit Type(::Wiz::Int::In Len) : m_Length(Len)
                    {}
                public:
                    ::Wiz::Bool::Type IsTrue() const            /// for ::Wiz::UnspecifiedBool::Type
                    {
                        return (m_Length != IllegalLength);
                    }
                public:
                    ::Wiz::Bool::Type IsValid() const
                    {
                        return IsTrue();
                    }
                    ::Wiz::Bool::Type NotValid() const
                    {
                        return !IsValid();
                    }
                public:
                    ::Wiz::Int::Type Length() const
                    {
                        return m_Length;
                    }
                public:
                    ::Wiz::Void::Type Concat(Type const& Other)
                    {
                        WIZ_ASSERT(this->IsValid() && Other.IsValid());
                        m_Length += Other.Length();
                    }
                protected:
                    ::Wiz::Int::Type            m_Length;
                }; /// end of class Type
            } /// end of namespace Base
            //////////////////////////////////////////////////////

            //////////////////////////////////////////////////////
            /// TYPE
            template <class T>
            class Type : public ::Wiz::BNF::Match::Base::Type
            {
            public:
                typedef ::Wiz::Optional::Type<T>            tValue;
                typedef typename tValue::tStorage           tCtorParam;
                typedef typename tValue::tStorage const&    tResult;
                typedef ::Wiz::BNF::Match::Base::Type       tSuper;
            public:
                Type() : tSuper()
                {}
                explicit Type(::Wiz::Size::In Len) : tSuper(Len)
                {}
                Type(::Wiz::Size::In Len, tCtorParam Val) : tSuper(Len), m_Value(Val)
                {
                }
                template <typename T2>
                Type(Type<T2> const& Other) : tSuper(Other.Length()), m_Value(Other.m_Value)
                {
                }
                template <>
                Type(Type<::Wiz::Null::Type> const& Other) : tSuper(Other.Length())
                {
                }
            public:
                template <typename T2>
                Type& operator=(Type<T2> const& Other)
                {
                    m_Length = Other.Length();
                    m_Value = Other.m_Value;
                    return *this;
                }
                template <>
                Type& operator=(Type<::Wiz::Null::Type> const& Other)
                {
                    m_Length = Other.Length();
                    return *this;
                }
            public:
                tResult Value() const
                {
                    WIZ_ASSERT(m_Value.IsValid());
                    return m_Value.Get();
                }
                template <typename ValueT>
                ::Wiz::Void::Type Value(ValueT const& Val)
                {
                    m_Value.Reset(Val);
                }
            protected:
                tValue                  m_Value;
            };

            template<>
            class Type<::Wiz::Null::Type> : public ::Wiz::BNF::Match::Base::Type
            {
            public:
                typedef ::Wiz::Null::Type               tValue;
                typedef ::Wiz::Null::Type               tReference;
                typedef ::Wiz::Null::Type               tResult;
                typedef ::Wiz::BNF::Match::Base::Type   tSuper;
            public:
                Type() : tSuper()
                {}
                explicit Type(::Wiz::Int::In Len) : tSuper(Len)
                {}
                Type(::Wiz::Int::In Len, ::Wiz::Null::Type) : tSuper(Len)
                {}
                template <typename T2>
                Type(Type<T2> const& Other) : tSuper(Other.Length())
                {}
            public:
                ::Wiz::Null::Type Value() const
                {
                    return ::Wiz::Null::Type();
                }
                ::Wiz::Void::Type Value(::Wiz::Null::Type)
                {
                }
            public:
                template <typename T2>
                Type& operator=(Type<T2> const& Other)
                {
                    m_Length = Other.Length();
                    return *this;
                }
            };
            //////////////////////////////////////////////////////
        } /// end of namespace Match
    } /// end of namespace BNF
} /// end of namespace Wiz

#endif /*__WIZ_BNF_MATCH_HPP__SHANHAOBO_19800429__*/
